package com.mobile.collect.utils;

import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import cn.droidlover.xdroidmvp.kit.NLog;

/**
 * 作者：李学伟
 * 日期：2018/7/12
 * 用途：
 */


public class FileUtil {


    /**
     * 创建文件
     *
     * @param path     文件所在目录的目录名，如/java/test/0.txt,要在当前目录下创建一个文件名为1.txt的文件，<br>
     *                 则path为/java/test，fileName为1.txt
     * @param fileName 文件名
     * @return 文件新建成功则返回true
     */
    public static boolean createFile(String path, String fileName) {
        File file = new File(path + File.separator + fileName);
        if (file.exists()) {
            Log.w("FileUtil", "新建文件失败：file.exist()=" + file.exists());
            return true;
        } else {
            try {
                boolean isCreated = file.createNewFile();
                return isCreated;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public static boolean createFile2(String path, String fileName) {
        File sd = Environment.getExternalStorageDirectory();
        File file = new File(sd.getPath() + File.separator + path + File.separator + fileName);
        if (file.exists()) {
            Log.w("FileUtil", "新建文件失败：file.exist()=" + file.exists());
            return true;
        } else {
            try {
                boolean isCreated = file.createNewFile();
                return isCreated;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 删除单个文件
     *
     * @param file 要删除的文件对象
     * @return 文件删除成功则返回true
     */
    public static boolean deleteFile(File file) {
        if (null != file && file.exists()) {
            Log.w("FileUtil", "删除路径" + file.getPath());
            boolean isDeleted = file.delete();
            Log.w("FileUtil", file.getName() + "删除结果：" + isDeleted);
            return isDeleted;
        } else {
            Log.w("FileUtil", "文件删除失败：文件不存在！");
            return false;
        }
    }

    /**
     * 删除单个文件
     *
     * @param path     文件所在路径名
     * @param fileName 文件名
     * @return 删除成功则返回true
     */
    public static boolean deleteFile(String path, String fileName) {
        File file = new File(path + File.separator + fileName);
        if (file.exists()) {
            boolean isDeleted = file.delete();
            return isDeleted;
        } else {
            return false;
        }
    }


    /**
     * 根据文件名获得文件的扩展名
     *
     * @return 文件扩展名（不带点）
     */
    public static String getFileSuffix(String filePath) {
        File file = new File(filePath);
        String fileName = "";
        if (null != file && file.exists()) {
            fileName = file.getName();
        }
        int index = fileName.lastIndexOf(".");
        String suffix = fileName.substring(index, fileName.length());
        return suffix;
    }

    /**
     * 根据文件名获得文件的名(不带后缀)
     */
    public static String getFileRealName(String filePath) {
        File file = new File(filePath);
        String fileName = "";
        if (null != file && file.exists()) {
            fileName = file.getName();
        }
        int index = fileName.lastIndexOf(".");
        String suffix = fileName.substring(0, index);
        return suffix;
    }

    /**
     * 重命名文件
     *
     * @param oldPath 旧文件的绝对路径
     * @param newPath 新文件的绝对路径
     * @return 文件重命名成功则返回true
     */
    public static boolean renameTo(String oldPath, String newPath) {
        if (oldPath.equals(newPath)) {
            Log.w("FileUtil", "文件重命名失败：新旧文件名绝对路径相同！");
            return false;
        }
        File oldFile = new File(oldPath);
        File newFile = new File(newPath);

        boolean isSuccess = oldFile.renameTo(newFile);
        Log.w("FileUtil", "文件重命名是否成功：" + isSuccess);
        return isSuccess;
    }

    /**
     * 重命名文件
     *
     * @param oldFile 旧文件对象
     * @param newFile 新文件对象
     * @return 文件重命名成功则返回true
     */
    public static boolean renameTo(File oldFile, File newFile) {
        if (oldFile.equals(newFile)) {
            Log.w("FileUtil", "文件重命名失败：旧文件对象和新文件对象相同！");
            return false;
        }
        boolean isSuccess = oldFile.renameTo(newFile);
        Log.w("FileUtil", "文件重命名是否成功：" + isSuccess);
        return isSuccess;
    }

    /**
     * 重命名文件
     *
     * @param oldFile 旧文件对象，File类型
     * @param newName 新文件的文件名，String类型
     * @return 重命名成功则返回true
     */
    public static boolean renameTo(File oldFile, String newName) {
        File newFile = new File(oldFile.getParentFile() + File.separator + newName);
        boolean flag = oldFile.renameTo(newFile);
        System.out.println(flag);
        return flag;
    }

    /**
     * 计算某个文件的大小
     *
     * @param file 文件对象
     * @return 文件大小，如果file不是文件，则返回-1
     */
    public static long getFileSize(File file) {
        if (file.isFile()) {
            return file.length();
        } else {
            return -1;
        }
    }

    /**
     * 计算某个文件的大小
     *
     * @param path 文件的绝对路径
     * @return
     */
    public static long getFileSize(String path) {
        File file = new File(path);
        long size = file.length();
        return size;
    }

    /**
     * 文件大小的格式化
     *
     * @param size 文件大小，单位为byte
     * @return 文件大小格式化后的文本
     */
    public static String formatSize(long size) {
        DecimalFormat df = new DecimalFormat("####.00");
        if (size < 1024) // 小于1KB
        {
            return size + "Byte";
        } else if (size < 1024 * 1024) // 小于1MB
        {
            float kSize = size / 1024f;
            return df.format(kSize) + "KB";
        } else if (size < 1024 * 1024 * 1024) // 小于1GB
        {
            float mSize = size / 1024f / 1024f;
            return df.format(mSize) + "MB";
        } else if (size < 1024L * 1024L * 1024L * 1024L) // 小于1TB
        {
            float gSize = size / 1024f / 1024f / 1024f;
            return df.format(gSize) + "GB";
        } else {
            return "size: error";
        }
    }

    /**
     * 格式化文件最后修改时间字符串
     *
     * @param time
     * @return
     */
    public static String formatTime(long time) {
        Date date = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd,HH:mm:ss", Locale.getDefault());
        String formatedTime = sdf.format(date);
        return formatedTime;
    }

    /**
     * 获取某个路径下的文件列表
     *
     * @param path 文件路径
     * @return 文件列表File[] files
     */
    public static File[] getFileList(String path) {
        File file = new File(path);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                return files;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 获取某个目录下的文件列表
     *
     * @param directory 目录
     * @return 文件列表File[] files
     */
    public static File[] getFileList(File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            return files;
        } else {
            return null;
        }
    }

    /**
     * 获得根目录文件列表
     *
     * @param showHidden
     * @param showHidden 是否显示隐藏文件
     * @return
     */
    public static List<File> getSDCardFileList(boolean showHidden) {
        List<File> list = new ArrayList<>();
        File files[];
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File extDir = Environment.getExternalStorageDirectory();
            files = extDir.listFiles();
            for (File file : files) {
                list.add(file);
            }
            if (showHidden) {
                //
            } else {
                for (int i = 0; i < list.size(); i++) {
                    File file = list.get(i);
                    if (file.isHidden() || file.getName().startsWith(".")) {
                        list.remove(file);
                    }
                }
            }
        } else {
        }
        return list;
    }

    /**
     * 新建目录
     *
     * @param path 目录的绝对路径
     * @return 创建成功则返回true
     */
    public static File createFolder(String path) {
        File file = new File(path);
        if (file.exists()) {
            return file;
        }else{
            file.mkdirs();
        }
        return file;
    }

    /**
     * 新建目录
     *
     * @param file
     * @return
     */
    public static boolean createFolder(File file) {
        boolean isCreated = file.mkdir();
        return isCreated;
    }

    /**
     * 删除文件夹及其包含的所有文件
     *
     * @param file
     * @return
     */
    public static boolean deleteFolder(File file) {
        boolean flag = false;
        File files[] = file.listFiles();
        if (files != null && files.length >= 0) // 目录下存在文件列表
        {
            for (int i = 0; i < files.length; i++) {
                File f = files[i];
                if (f.isFile()) {
                    // 删除子文件
                    flag = deleteFile(f);
                    if (flag == false) {
                        return flag;
                    }
                } else {
                    // 删除子目录
                    flag = deleteFolder(f);
                    if (flag == false) {
                        return flag;
                    }
                }
            }
        }
        flag = file.delete();
        if (flag == false) {
            return flag;
        } else {
            return true;
        }
    }


    /**
     * 获取待复制文件夹的文件夹名
     *
     * @param dir
     * @return String
     */
    public static String getDirName(String dir) {
        if (dir.endsWith(File.separator)) {
            // 如果文件夹路径以"//"结尾，则先去除末尾的"//"
            dir = dir.substring(0, dir.lastIndexOf(File.separator));
        }
        return dir.substring(dir.lastIndexOf(File.separator) + 1);
    }

    /**
     * 计算某个目录包含的文件数量
     *
     * @param directory
     * @return
     */
    public static int getFileCount(File directory) {
        File[] files = directory.listFiles();
        int count = files.length;
        return count;
    }

    /**
     * 计算某个路径下所包含的文件数量
     *
     * @param path
     * @return
     */
    public static int getFileCount(String path) {
        File file = new File(path);
        File[] files = file.listFiles();
        int count = files.length;
        return count;
    }

    /**
     * 计算某个目录的大小
     *
     * @return
     */
    public static long getFolderSize(File directory) {
        File[] files = directory.listFiles();
        if (files != null && files.length >= 0) {
            long size = 0;
            for (File f : files) {
                if (f.isFile()) {
                    // 获得子文件的大小
                    size = size + getFileSize(f);
                } else {
                    // 获得子目录的大小
                    size = size + getFolderSize(f);
                }
            }
            return size;
        }
        return -1;
    }

    /**
     * 获得某个文件或目录的大小
     *
     * @param file
     * @return
     */
    public static long getFileOrFolderSize(File file) {
        long size = 0;
        if (file.isDirectory()) {
            size = getFolderSize(file);
        } else {
            size = getFileSize(file);
        }
        return size;
    }

    public static String createTaskPicDir(String dir) {

        File targetDirFile = new File(dir);
        if (!targetDirFile.exists()) {
            targetDirFile.mkdir();
        }
        createFolder(dir);
        return dir;
    }


//    public static String getPicDir(String type, String taskId) {
//        String path = createTaskPicDir(type, taskId);
//        return path;
//    }

    public static File getTmpPicFile(String picTmpName) {
        File directory = Environment.getExternalStorageDirectory();
        String targetDir = createTaskPicDir(directory.getPath()+"/tmp");
        boolean result = createFile(targetDir, picTmpName);
        if (result) {
            return new File(targetDir, picTmpName);
        } else {
            return null;
        }
    }


    public static File getFile(String dir, String fileName) {
//        String targetDir = createTaskPicDir("resultFiles");
        boolean result = createFile(dir, fileName);
        if (result) {
            return new File(dir + File.separator + fileName);
        } else {
            return null;
        }
    }


    public static void writeFile(InputStream inputStream, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int ch = 0;
            while ((ch = inputStream.read()) != -1) {
                os.write(ch);
            }
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public static long readSDCardAvailSpace(String sdPath) {
        File sdcardDir = new File(sdPath);
        StatFs sf = new StatFs(sdcardDir.getPath());
        long blockSize = sf.getBlockSize();
        long blockCount = sf.getBlockCount();
        long availCount = sf.getAvailableBlocks();
        Log.d("FileUtil", "block大小:" + blockSize + ",block数目:" + blockCount + ",总大小:" + blockSize * blockCount / 1024 + "KB");
        Log.d("FileUtil", "可用的block数目：:" + availCount + ",剩余空间:" + availCount * blockSize);
        return availCount * blockSize / 1024 / 1024;
    }

    public static long readSDCardAllSpace(String sdPath) {
        File sdcardDir = new File(sdPath);
        StatFs sf = new StatFs(sdcardDir.getPath());
        long blockSize = sf.getBlockSize();
        long blockCount = sf.getBlockCount();
        long sdSize = blockSize * blockCount / 1024 / 1024;
        NLog.e("readSDCardAllSpace", "sdSize = " + sdSize);
        return blockSize * blockCount / 1024 / 1024;
    }

    public static long readUSBSpace(String sdPath) {
        File sdcardDir = new File(sdPath);
        StatFs sf = new StatFs(sdcardDir.getPath());
        long blockSize = sf.getBlockSize();
        long blockCount = sf.getBlockCount();
//        long availCount = sf.getAvailableBlocks();
        Log.d("FileUtil", "block大小:" + blockSize + ",block数目:" + blockCount + ",总大小:" + blockSize * blockCount / 1024 + "KB");
        return blockSize * blockSize / 1024 / 1024;
    }

    public static String getStoragePath(Context mContext) {
//        getPhysicalExternalFilePathAboveM();
        String sdCardPath = null;
        StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);

        Class<?> storageVolumeClazz = null;
        try {
            storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
            Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
            Method getPath = storageVolumeClazz.getMethod("getPath");
            Method getPathFile = storageVolumeClazz.getMethod("getPathFile");
            Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
            Method isEmulated = storageVolumeClazz.getMethod("isEmulated");
            Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
            Method getMaxFileSize = storageVolumeClazz.getMethod("getMaxFileSize");
            Method getState = storageVolumeClazz.getMethod("getState");
            Object result = getVolumeList.invoke(mStorageManager);
            final int length = Array.getLength(result);
            for (int i = 0; i < length; i++) {
                Object storageVolumeElement = Array.get(result, i);
                String path = (String) getPath.invoke(storageVolumeElement);
                File file = (File) getPathFile.invoke(storageVolumeElement);
                Boolean isEmulate = (Boolean) isEmulated.invoke(storageVolumeElement);
                Boolean mPrimary = (Boolean) isPrimary.invoke(storageVolumeElement);
                Long MaxFileSize = (Long) getMaxFileSize.invoke(storageVolumeElement);
                String STATE = (String) getState.invoke(storageVolumeElement);
                NLog.e("", "file = " + file);
                if (null != file) {
                    NLog.e("getStoragePath", "file = " + file.getPath());
                    NLog.e("getStoragePath", "isEmulate = " + isEmulate);
                    NLog.e("getStoragePath", "mPrimary = " + mPrimary);
                    NLog.e("getStoragePath", "MaxFileSize = " + MaxFileSize);
                    NLog.e("getStoragePath", "STATE = " + STATE);
                }
                boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
                if (removable && TextUtils.isEmpty(sdCardPath) && !TextUtils.isEmpty(path) && path.contains("external_sd")) {
                    NLog.e("getStoragePath", "path=" + path);

                    sdCardPath = path;
//                    break;
                }
//                NLog.d("FileUtil",i+"--path = "+path);

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        NLog.d("FileUtil", "sdCardPath == " + sdCardPath);
        String storePath = Environment.getExternalStorageDirectory().toString(); // 文件保存路径
        NLog.d("FileUtil", "storePath == " + storePath);
        if (TextUtils.isEmpty(sdCardPath) || readSDCardAllSpace(sdCardPath) < 8 * 1024) {
//        if (TextUtils.isEmpty(sdCardPath)) {
            NLog.e("getStoragePath", "getExternalStorageDirectory");
            sdCardPath = Environment.getExternalStorageDirectory().toString(); // 文件保存路径
        }
        return sdCardPath;
    }


    /**
     * 复制单个文件
     *
     * @param oldPath$Name String 原文件路径+文件名 如：data/user/0/com.test/files/abc.txt
     * @param newPath$Name String 复制后路径+文件名 如：data/user/0/com.test/cache/abc.txt
     * @return <code>true</code> if and only if the file was copied;
     * <code>false</code> otherwise
     */
    public static boolean copyFile(String oldPath$Name, String newPath$Name) {
        try {
            File oldFile = new File(oldPath$Name);
            if (!oldFile.exists()) {
                Log.e("--Method--", "copyFile:  oldFile not exist.");
                return false;
            } else if (!oldFile.isFile()) {
                Log.e("--Method--", "copyFile:  oldFile not file.");
                return false;
            } else if (!oldFile.canRead()) {
                Log.e("--Method--", "copyFile:  oldFile cannot read.");
                return false;
            }

        /* 如果不需要打log，可以使用下面的语句
        if (!oldFile.exists() || !oldFile.isFile() || !oldFile.canRead()) {
            return false;
        }
        */

            FileInputStream fileInputStream = new FileInputStream(oldPath$Name);    //读入原文件
            FileOutputStream fileOutputStream = new FileOutputStream(newPath$Name);
            byte[] buffer = new byte[1024];
            int byteRead;
            while ((byteRead = fileInputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, byteRead);
            }
            fileInputStream.close();
            fileOutputStream.flush();
            fileOutputStream.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public static String getFromAssets(Context context,String fileName){
        try {
            InputStreamReader inputReader = new InputStreamReader(context.getResources().getAssets().open(fileName) );
            BufferedReader bufReader = new BufferedReader(inputReader);
            String line="";
            String Result="";
            while((line = bufReader.readLine()) != null)
                Result += line;
            return Result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }



}
